package com.example.waterdispenserm2.vmc;


import android.os.SystemClock;

import com.aill.androidserialport.SerialPort;
import com.example.waterdispenserm2.util.MyLog;
import com.example.waterdispenserm2.util.SPUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class SerialPortHelper {
    private static final String TAG = "SerialPortHelper";
    private static final String DEFAULT_PORT = "/dev/ttyS0"; // 默认串口设备
    private static final int DEFAULT_BAUDRATE = 9600;       // 默认波特率

    private SerialPort mSerialPort;
    private InputStream mInputStream;
    private OutputStream mOutputStream;
    private ReadThread mReadThread;
    private ScheduledExecutor mScheduledExecutor;
    private boolean isConnected = false;
    private SerialDataListener mDataListener;

    // 串口数据监听接口
    public interface SerialDataListener {
        void onDataReceived(byte[] data);           // 数据接收回调
        void onConnectionChanged(boolean connected); // 连接状态变化回调
    }

    public SerialPortHelper(SerialDataListener listener) {
        this.mDataListener = listener;
        this.mScheduledExecutor = new ScheduledExecutor();
    }

    /**
     * 连接到默认串口
     */
    public void connect() {
        connect(SPUtils.getSerialPortNum(), DEFAULT_BAUDRATE);
    }

    /**
     * 连接到指定串口
     * @param port 串口设备路径
     * @param baudrate 波特率
     */
    public void connect(String port, int baudrate) {
        try {
            MyLog.i(TAG, "port="+port+"--baudrate-"+baudrate);
            // 创建串口实例
            mSerialPort = new SerialPort(new File(port), baudrate, 0);
            mInputStream = mSerialPort.getInputStream();
            mOutputStream = mSerialPort.getOutputStream();

            // 启动数据读取线程
            startReadThread();

            isConnected = true;
            if (mDataListener != null) {
                mDataListener.onConnectionChanged(true);
            }
            // 启动心跳检测
            mScheduledExecutor.startHeartbeat();
            MyLog.i(TAG, "Serial port connected successfully");
        } catch (IOException e) {
            MyLog.e(TAG, "Serial port connection failed: " + e.getMessage());
            handleDisconnection();
        }
    }

    /**
     * 启动数据读取线程
     */
    private void startReadThread() {
        stopReadThread(); // 确保之前的线程已停止
        mReadThread = new ReadThread();
        mReadThread.start();
    }

    /**
     * 停止数据读取线程
     */
    private void stopReadThread() {
        if (mReadThread != null) {
            mReadThread.interrupt();
            mReadThread = null;
        }
    }

    /**
     * 断开串口连接
     */
    public void disconnect() {
        try {
            stopReadThread();
            if (mInputStream != null) mInputStream.close();
            if (mOutputStream != null) mOutputStream.close();
            if (mSerialPort != null) mSerialPort.close();
            MyLog.i(TAG, "Serial port disconnected");
        } catch (IOException e) {
            MyLog.e(TAG, "Error while disconnecting: " + e.getMessage());
        }
        handleDisconnection();
    }

    /**
     * 处理断开连接逻辑
     */
    private void handleDisconnection() {
        isConnected = false;
        if (mDataListener != null) {
            mDataListener.onConnectionChanged(false);
        }
        mScheduledExecutor.scheduleReconnect(); // 安排重连
    }

    /**
     * 发送数据到串口
     * @param data 要发送的数据
     * @return 发送是否成功
     */
    public boolean sendData(byte[] data) {
        if (!isConnected || mOutputStream == null) {
            MyLog.w(TAG, "Cannot send data: not connected");
            return false;
        }

        try {
            mOutputStream.write(data);
            mOutputStream.flush();
            MyLog.d(TAG, "Data sent: " + bytesToHex(data));
            return true;
        } catch (IOException e) {
            MyLog.e(TAG, "Error while sending data: " + e.getMessage());
            handleDisconnection();
            return false;
        }
    }

    /**
     * 数据读取线程
     */
    private class ReadThread extends Thread {
        @Override
        public void run() {
            byte[] buffer = new byte[1024];
            while (!isInterrupted() && isConnected) {
                try {
                    if (mInputStream.available() > 0) {
                        SystemClock.sleep(100);
                        int size = mInputStream.read(buffer);
                        if (size > 0) {
                            byte[] received = Arrays.copyOf(buffer, size);
                            MyLog.d(TAG, "Data received: " + bytesToHex(received));

                            if (mDataListener != null) {
                                mDataListener.onDataReceived(received);
                            }
                        }
                    }
                    SystemClock.sleep(50);// 短暂休眠减少CPU占用
                } catch (Exception e) {
                    MyLog.e(TAG, "Error in read thread: " + e.getMessage());
                    handleDisconnection();
                    break;
                }
            }
        }
    }

    /**
     * 定时任务执行器
     * 负责心跳检测和自动重连
     */
    private class ScheduledExecutor {
        private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        private static final int HEARTBEAT_INTERVAL = 4;  // 心跳间隔(秒)
        private static final int RECONNECT_DELAY = 3;     // 重连延迟(秒)

        /**
         * 启动心跳检测
         * 定期发送IO状态查询指令
         * scheduleAtFixedRate
         */
        void startHeartbeat() {
            executor.scheduleWithFixedDelay(() -> {
                if (isConnected) {
                    byte[] query = CommandBuilder.buildQueryIO();
                    sendData(query);
                    MyLog.d(TAG, "Sending heartbeat query");
                }
            }, HEARTBEAT_INTERVAL, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
        }

        /**
         * 安排重连任务
         */
        void scheduleReconnect() {
            executor.schedule(() -> {
                if (!isConnected) {
                    MyLog.i(TAG, "Attempting to reconnect...");
                    connect();
                }
            }, RECONNECT_DELAY, TimeUnit.SECONDS);
        }
    }

    /**
     * 字节数组转十六进制字符串
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }
}